////////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010 Leon Coto Rodriguez
//  leoncoto@gmail.com
//  
//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation
//  files (the "Software"), to deal in the Software without
//  restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following
//  conditions:
//  
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//  
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//  OTHER DEALINGS IN THE SOFTWARE.
//
////////////////////////////////////////////////////////////////////////////////

package org.flexspeedup.model
{

import mx.events.PropertyChangeEvent;
import mx.utils.ObjectProxy;
import flash.utils.flash_proxy;

use namespace flash_proxy;

/**
 *  Application wide configuration values
 *  Based on http://code.google.com/p/rojored/source/browse/trunk/src/com/rojored/model/config/Settings.as
 *  by Gabriel Montagné Láscaris-Comneno gabriel@rojored.com
 * 
 *  Settings class that can work as as a dynamic but bindable config data model
 *  meant to represent a simple configuration XML.
 *
 *  <p>Properties defined on a simple XML will be proxied by this class.  Views
 *  can be bound to these properties even before the config has been processed
 *  (loaded, etc.) After the config has been processed, though, if you try to
 *  read a property that wasn't defined in the XML, this object will throw a
 *  runtime error.</p>
 * 
 *  <p>Based and inspired on work by danny patterson (dannypatterson.com),
 *  kadazuro (kadazuro.com) and michael labriola (digitalprimates.net).</p>
 * 
 */
dynamic public class Settings extends ObjectProxy
{
    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------
    
    /**
     * Returns a new instance of this class.
     */
    public function Settings()
    {
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  propertyMap
    //----------------------------------
    /**
     *  @private
     */
    private var propertyMap:Object;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  data
    //----------------------------------
    /**
     *  @private
     */
    private var _data:XMLList;
    
    /**
     * An <code>XMLList</code> with the settings data
     */
    public function get data():XMLList
    {
        return _data;
    }
    
    /**
     *  @private
     */    
    public function set data(value:XMLList):void
    {
        if (value == _data || value == null)
            return;
        _data = value;
        createPropertyMap(_data);
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    flash_proxy override function getProperty(name:*):*
    {
        if (!propertyMap)
            return "";
        
        var property:* = propertyMap[name];
        if (!property)
        {
            throw new Error("Property " + name + " not found");
            return "";
        }
        return property;
    }

    /**
     *  @private
     */
    flash_proxy override function setProperty(name:*, value:*):void
    {
        var oldValue:* = propertyMap[name];
        propertyMap[name] = value;
        dispatchEvent(
            PropertyChangeEvent.createUpdateEvent(
                this,
                name,
                oldValue,
                value
            )
        );
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    private function createPropertyMap(data:XMLList):void
    {
        propertyMap = {};
        for each (var element:XML in data)
            setProperty(element.@id, element.toString());
    }
}
}